package com.ms.teapuesto.util;

import org.apache.commons.functor.UnaryFunction;
import org.apache.commons.functor.UnaryPredicate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.util.*;

/**
 * User: RAC
 * Date: 04/10/12
 */
public class ListUtil {
    protected static Log logger = LogFactory.getLog(ListUtil.class);


    public static <E> List<E> getSubList(Collection<E> list, UnaryPredicate predicate) {
        List subList = new ArrayList();
        for (E o : list) {
            if (predicate.test(o)) {
                subList.add(o);
            }
        }
        return subList;
    }

    public static <E> List<E> getRepeatList(Collection<E> base, Collection<E> list) {
        List<E> result = new ArrayList<E>();
        int count = 0;
        for (E o : base) {
            count = 0;
            for (E item : list) {
                if (o.equals(item)) {
                    count++;
                }
            }
            if (count > 1) {
                result.add(o);
            }
        }
        return result;
    }

    public static List<Object> getList(Collection list, UnaryFunction unaryFunction) {
        List<Object> newList = new ArrayList<Object>();
        for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
            Object obj = iterator.next();
            newList.add(unaryFunction.evaluate(obj));

        }
        return newList;
    }

    public static Set columnAsSet(Collection list, String propertyName, UnaryPredicate predicate) {
        final Collection subList = new HashSet(list.size());
        return (Set) columnAsList(list, propertyName, predicate, subList);
    }

    public static <E> E columnFindFirst(Collection<E> list, String propertyName, final Object value) {
        List<E> matches = columnFindList(list, propertyName, value);
        return matches.size() == 0 ? null : matches.get(0);
    }

    public static <E> List<E> columnFindList(Collection<E> list, String propertyName, final Object value) {
        FindUnaryFunction findFunction = new FindUnaryFunction(propertyName, value);
        apply(list, null, findFunction);
        return findFunction.getList();
    }

    private static Collection columnAsList(Collection list, final String propertyName, UnaryPredicate predicate, final Collection subList) {
        PropertyUnaryFunction unaryFunction = new PropertyUnaryFunction(propertyName) {
            protected Object evaluate(Object bean, Object propertyValue) {
                subList.add(propertyValue);
                return null;
            }
        };
        apply(list, predicate, unaryFunction);
        return subList;
    }

    public static List<List> getGroups(Collection list, int maximo) {
        int i = 0;
        List<List> result = new ArrayList<List>();
        List<Object> parcial = new ArrayList<Object>();
        for (Object bean : list) {
            i++;
            if (i < maximo) {
                parcial.add(bean);
            } else {
                parcial.add(bean);
                result.add(parcial);
                parcial = new ArrayList<Object>();
                i = 0;
            }
        }
        if (parcial.size() > 0) {
            result.add(parcial);
        }
        return result;
    }

    public static void main(String[] args) {
        List<String> list= Arrays.asList("A", "E", "A", "O", "1", "1", "2", "3", "4", "1");
        List<String> base = Arrays.asList("A", "E", "I", "O", "U", "1", "2", "3", "4", "5");

        System.out.println(getRepeatList(base,list));

    }

    public static <E> List<E> getSubList(Collection<E> list, final String propertyName, final Object propertyValue) {
        return getSubList(list, new UnaryPredicate() {
            public boolean test(Object o) {
                BeanWrapper wrapper = new BeanWrapperImpl(o);
                return propertyValue.equals(wrapper.getPropertyValue(propertyName));
            }
        });
    }

    private static Object getPropertyValue(BeanWrapper wrap, String propertyNameValue, boolean assumeNullValueOnError) {
        Object value;
        if (assumeNullValueOnError)
            value = wrap.isReadableProperty(propertyNameValue)
                    ? wrap.getPropertyValue(propertyNameValue)
                    : null;
        else
            value = wrap.getPropertyValue(propertyNameValue);
        return value;
    }

    public static void apply(Collection list, UnaryPredicate predicate, UnaryFunction function) {
        for (Object o : list) {
            if (predicate == null || predicate.test(o)) {
                function.evaluate(o);
            }
        }
    }
}
